import { defineComponent, ref, reactive, shallowRef, onMounted, onBeforeUnmount } from 'vue'
import { ElLoading } from 'element-plus'
import type { HomeAreaType, HomeMapStateType } from './typings'
import type { LoadingInstance } from 'element-plus/es/components/loading/src/loading'
import { useStore } from 'vuex'
import useAMap from '~/hooks/useAMap'
import lampost from '~/assets/lightPoleOn.png'

export default defineComponent({
  name: 'HomeMap',
  props: ['id', 'initCallback', 'getMapZoom', 'markerIconOptions'],
  emits: [
    'changePatterMarkerInfoView',
    'changePatterMarkerInfoPosition',
    'handleSearchMapMarkerByModuleId',
    'getMarkerInfo'
  ],
  setup(props: HomeAreaType, { expose, emit }) {
    const store = useStore()
    const mapDomRef = ref()
    const state = reactive<HomeMapStateType>({
      mapCenter: [],
      polygon: {},
      areaCenterMarker: {}
    })
    const [mapRef, aMapRef] = useAMap(
      props.id,
      {
        zoom: 12,
        mapStyle: 'amap://styles/whitesmoke'
      },
      initAMap
    )

    // 设置地图中心点和地图层级
    const handleSetMapInfo = (mapData: Record<string, any>) => {
      if (mapRef.value && mapData) {
        state.mapCenter = [mapData.lon, mapData.lat]
        mapRef.value.setZoomAndCenter(mapData.layerLevel, state.mapCenter, false, 0)
        props.getMapZoom?.()
      }
    }

    //  地区查询
    const district = shallowRef()
    const polygon = ref(null)
    const loadSearchRef = ref<LoadingInstance>()
    const handleSearchDistribution = (positionName: string) => {
      loadSearchRef.value = ElLoading.service({
        target: `#${props.id}`,
        text: '地图渲染中，请稍后'
      })
      if (!district.value) {
        district.value = new aMapRef.value.DistrictSearch({
          subdistrict: 0,
          extensions: 'all',
          level: 'district'
        })
      }
      // district.value.setLevel(position)
      district.value.search(positionName, (status: any, result: any) => {
        if (polygon.value) {
          mapRef.value.remove(polygon.value)
          polygon.value = null
        }
        const bounds = result.districtList[0].boundaries
        if (bounds) {
          for (let i = 0; i < bounds.length; i += 1) {
            bounds[i] = [bounds[i]]
          }
          polygon.value = new aMapRef.value.Polygon({
            strokeWeight: 1,
            path: bounds,
            fillOpacity: 0.4,
            fillColor: '#80d8ff',
            strokeColor: '#0091ea'
          })
          mapRef.value.add(polygon.value)
          mapRef.value.setFitView(polygon.value)

          loadSearchRef.value!.close()
        }
      })

      loadSearchRef.value!.close()
    }

    //  生产工区
    const handleGeneratePolygon = (polygonData: Record<string, any>) => {
      //  工区面
      const objPolygon: any = {}
      objPolygon[polygonData.name] = new aMapRef.value.Polygon({
        map: mapRef.value,
        path: polygonData.coordinates,
        fillColor: polygonData.backColor,
        strokeColor: polygonData.bordeColor,
        strokeWeight: polygonData.width ?? 1,
        zooms: polygonData.zooms,
        bubble: true,
        extData: polygonData
      })
      Object.assign(state.polygon, objPolygon)

      //  工区信息
      const objText: any = {}
      const position = JSON.parse(polygonData.centerPoint)
      objText[polygonData.name] = new aMapRef.value.Text({
        map: mapRef.value,
        position,
        zooms: polygonData.zooms,
        text: polygonData.assetModelInfoDataVO?.infoList
          ? `
          <section style="padding: 8px 16px; font-size: 16px; font-weight: 500;">${
            polygonData.name
          }</section>
          <section class="area-info-content">
            ${
              polygonData.assetModelInfoDataVO?.infoList
                ?.map(
                  (item: Record<string, string>) => `<p>${item.key || ''}: ${item.value || ''}</p>`
                )
                ?.join('') || ''
            }
          </section>
        `
          : `<section style="padding: 8px 16px; font-size: 16px; font-weight: 500;">${polygonData.name}</section>`
      })
      Object.assign(state.areaCenterMarker, objText)
    }
    //  工区显示隐藏(单个)
    const polygonLegend = (row: any) => {
      if (row.check) {
        state.polygon[row.status].show()
        state.areaCenterMarker[row.status].show()
      } else {
        state.polygon[row.status].hide()
        state.areaCenterMarker[row.status].hide()
      }
    }
    //  工区显示隐藏(全部)
    const polygonLabelsLayerSwitch = (value: boolean) => {
      for (const key in state.polygon) {
        if (value) {
          state.polygon[key].show()
          state.areaCenterMarker[key].show()
        } else {
          state.polygon[key].hide()
          state.areaCenterMarker[key].hide()
        }
      }
    }
    //  卫星地图展示切换
    const satellite = shallowRef()
    const satelliteChangingOver = (value: boolean) => {
      if (!value) {
        mapRef.value.removeLayer(satellite.value)
      } else {
        mapRef.value.addLayer(satellite.value)
      }
    }
    //  动态生成图层
    const trendsLabelsLayer = (list: any) => {
      const obj: any = {}
      for (const key in list) {
        obj![key] = new aMapRef.value.LabelsLayer({
          // visible: true,
          collision: false
          // allowCollision: false
        })
        mapRef.value.addLayer(obj![key])
      }
      state.markerLabelsLayer = obj
    }
    //  海量点标点
    const markerMap = new Map()
    const markerLabelsLayer = (list: any) => {
      for (const key in props.markerIconOptions) {
        state.markerLabelsLayer![key].clear()
      }
      if (list.length === 0) return
      for (let i = 0; i < list.length; i++) {
        const item = list[i]
        const phase = item.phase ? item.phase : null
        if (phase) {
          const marker = new aMapRef.value.LabelMarker({
            position: phase?.coordinates,
            name: item?.name,
            icon: {
              type: 'image',
              image: props.markerIconOptions![item.moduleId]?.icons[item!.isDeliverStr]?.iconUrl,
              size: props.markerIconOptions![item.moduleId]?.icons[item!.isDeliverStr]?.iconSize
            },
            text: {
              content: item.name,
              direction: 'top',
              zooms: [18, 20],
              style: {
                fillColor: '#d9001b'
                // strokeColor: '#ffffff'
              }
            },
            extData: item,
            zooms:
              props.markerIconOptions![item.moduleId].zooms?.length &&
              props.markerIconOptions![item.moduleId].zooms
          })
          marker.on('click', handleClickPatterMarker)
          markerMap.set(item.id, marker)
          state.markerLabelsLayer![item.moduleId].add(marker)
        }
      }
    }
    // 显示部分点
    const setMarkersVisible = (showList: any, hideList: any) => {
      showList.forEach((id: string) => {
        markerMap.get(id) && markerMap.get(id).show()
      })
      hideList.forEach((id: string) => {
        markerMap.get(id) && markerMap.get(id).hide()
      })
    }
    //  海量点标点图层显隐
    const markerLabelsLayerSwitch = (array: any) => {
      for (const key in props.markerIconOptions) {
        if (array.indexOf(key) === -1) {
          state.markerLabelsLayer![key].hide()
        } else {
          state.markerLabelsLayer![key].show()
        }
      }
    }
    //  点击点位
    const handleClickPatterMarker = async (markerEvent: Record<string, any>) => {
      const extData = markerEvent.target.getExtData()
      selectedMarker(extData)
      //  判断是否显示点位详情弹框
      if (props.markerIconOptions![extData.moduleId]?.infoVisible === 0) return
      const mapClientRect = mapDomRef.value.getBoundingClientRect()
      const patternMarkerOffset = mapRef.value.lngLatToContainer(markerEvent.target!.getPosition())
      // 将获取到的 left top 数据发送给父组建
      const { markerType, data } = await handleGetPatterMarkerInfoBy(extData)
      if (!data) return
      state.activePatternMarker = markerEvent.target
      emit(
        'changePatterMarkerInfoView',
        patternMarkerOffset.x + mapClientRect.left,
        patternMarkerOffset.y + mapClientRect.top,
        markerType,
        data
      )
      // 给map注册拖动事件 让popover 随着拖动移动
      mapRef.value.on('mapmove', handleReplacePatterDomOffset)
      mapRef.value.on('resize', handleReplacePatterDomOffset)
    }
    //  点击选中图表变大
    const infoMarker = shallowRef()
    const selectedMarker = (extData?: any) => {
      if (infoMarker.value) {
        mapRef.value.remove(infoMarker.value)
      }
      const icon = new aMapRef.value.Icon({
        size: props.markerIconOptions![extData.moduleId]?.icons[extData!.isDeliverStr]?.bigIconSize,
        imageSize:
          props.markerIconOptions![extData.moduleId]?.icons[extData!.isDeliverStr]?.bigIconSize,
        image: props.markerIconOptions![extData.moduleId]?.icons[extData!.isDeliverStr]?.iconUrl
      })
      infoMarker.value = new aMapRef.value.Marker({
        map: mapRef.value,
        position: extData.phase.coordinates,
        offset: [-15, -30],
        icon,
        extData,
        zooms:
          props.markerIconOptions![extData.moduleId].zooms?.length &&
          props.markerIconOptions![extData.moduleId].zooms,
        zIndex: 9999
      })

      infoMarker.value.on('click', handleClickPatterMarker)
    }
    //  清除点击放大点位
    const selectedMarkerRemove = () => {
      if (infoMarker.value) {
        mapRef.value.remove(infoMarker.value)
      }
    }
    // 地图拖拽时的回调
    const handleReplacePatterDomOffset = () => {
      const mapClientRect = mapDomRef.value.getBoundingClientRect()
      const patternMarkerOffset = mapRef.value.lngLatToContainer(
        state.activePatternMarker!.getPosition()
      )
      if (mapClientRect && patternMarkerOffset) {
        // 将获取到的 left top 和 工区数据发送给父组建
        emit(
          'changePatterMarkerInfoPosition',
          patternMarkerOffset.x + mapClientRect.left,
          patternMarkerOffset.y + mapClientRect.top - 2
        )
      }
    }
    //  获取点位信息数据
    const handleGetPatterMarkerInfoBy = async (extData: any) => {
      emit('getMarkerInfo', extData)
      let markerType = ''
      const { code, data } = await store.dispatch(
        'assetHome/GetAssetHomePopoverInfoDataByIdStationGisApi',
        {
          assetId: extData?.id,
          specialCode: 'basestation_home'
        }
      )
      if (code === 200) {
        //  BaseStation BaseBuild
        markerType = data?.moduleCode
        return {
          markerType,
          data
        }
      }
      return {
        markerType: undefined,
        data: undefined
      }
    }
    //  画圆 114.17045&lat=30.58326
    let drawCircleIds = reactive<number[]>([])
    const drawCircleOverlayGroup = shallowRef()
    const drawCircle = (radius: number, center: number[]) => {
      if (drawCircleIds.indexOf(center[0]) === -1) {
        drawCircleIds.push(center[0])
        const circle = new aMapRef.value.Circle({
          center: new aMapRef.value.LngLat(center[0], center[1]),
          radius,
          borderWeight: 2,
          strokeOpacity: 0,
          strokeDasharray: [10, 10],
          fillColor: '#ee2200',
          fillOpacity: 0.2
        })
        drawCircleOverlayGroup.value.addOverlay(circle)
      }
    }
    //  附近灯杆
    let drawLamppostIds = reactive<string[]>([])
    let drawLamppostMarker = reactive<any[]>([])
    const appendixLabelMarker = shallowRef()
    const appendixLamppostDraw = (list: Record<string, any>[]) => {
      for (let i = 0; i < list.length; i++) {
        const item = list[i]
        if (drawLamppostIds.indexOf(item.id) === -1) {
          drawLamppostIds.push(item.id)
          const markers = new aMapRef.value.LabelMarker({
            position: item.phase.coordinates,
            name: item?.code,
            icon: {
              type: 'image',
              image: lampost,
              size: [28, 28]
            },
            text: {
              content: item.code,
              direction: 'top',
              style: {
                fillColor: '#d9001b',
                strokeColor: '#ffffff'
              }
            },
            extData: item
          })
          drawLamppostMarker.push(markers)
          markers.on('click', appendixLamppostInfo)
        }
      }
      appendixLabelMarker.value.add(drawLamppostMarker)
    }
    //  附近灯杆详情
    const appendixLamppostInfo = async (markerEvent: Record<string, any>) => {
      const extData = markerEvent.target.getExtData()
      const { data } = await store.dispatch('base/GetLampPostById', { id: extData.id })
      if (!data) return
      const mapClientRect = mapDomRef.value.getBoundingClientRect()
      const patternMarkerOffset = mapRef.value.lngLatToContainer(markerEvent.target!.getPosition())
      state.activePatternMarker = markerEvent.target
      const datainfo = {
        name: data.code,
        assetId: extData.id,
        moduleCode: 'lightPole',
        moduleName: '灯杆',
        infoList: [
          { type: 'text', key: '灯杆经度', value: data.lon },
          { type: 'text', key: '灯杆纬度', value: data.lat },
          { type: 'text', key: '详细地址', value: data.address }
        ]
      }
      emit(
        'changePatterMarkerInfoView',
        patternMarkerOffset.x + mapClientRect.left,
        patternMarkerOffset.y + mapClientRect.top - 18,
        'BaseStation',
        datainfo,
        []
      )
      // 给map注册拖动事件 让popover 随着拖动移动
      mapRef.value.on('mapmove', handleReplacePatterDomOffset)
      mapRef.value.on('resize', handleReplacePatterDomOffset)
    }
    //  清空圆/灯杆
    const drawCircleCrea = () => {
      drawCircleIds = []
      drawLamppostIds = []
      drawLamppostMarker = []
      appendixLabelMarker.value.clear()
      drawCircleOverlayGroup.value.clearOverlays()
    }
    //  数据更新
    const handleSearchMapMarkerByModuleId = () => {
      emit('handleSearchMapMarkerByModuleId')
    }

    //  地图初始化
    async function initAMap() {
      await props.initCallback()

      //  地图缩放
      mapRef.value.on('zoomend', () => {
        props.getMapZoom?.()
        handleSearchMapMarkerByModuleId()
      })
      //  地图拖拽
      mapRef.value.on('moveend', handleSearchMapMarkerByModuleId)

      //  卫星图层
      satellite.value = new aMapRef.value.TileLayer.Satellite()

      //  附近灯杆图层
      appendixLabelMarker.value = new aMapRef.value.LabelsLayer({
        visible: true,
        collision: false,
        allowCollision: false
      })
      mapRef.value.add(appendixLabelMarker.value)

      //  圆集合
      drawCircleOverlayGroup.value = new aMapRef.value.OverlayGroup()
      mapRef.value.add(drawCircleOverlayGroup.value)
    }

    onMounted(() => {})
    onBeforeUnmount(() => {
      mapRef.value.clearMap()
      mapRef.value.destroy()
    })

    expose({
      map: mapRef,
      aMap: aMapRef,
      handleSetMapInfo,
      handleSearchDistribution,
      satelliteChangingOver,
      trendsLabelsLayer,
      markerLabelsLayer,
      markerLabelsLayerSwitch,
      drawCircle,
      drawCircleCrea,
      appendixLamppostDraw,
      handleGeneratePolygon,
      polygonLegend,
      polygonLabelsLayerSwitch,
      setMarkersVisible,
      selectedMarkerRemove
    })
    return () => (
      <>
        <section id={props.id} ref={mapDomRef}></section>
      </>
    )
  }
})
